package com.improvess.rna.som;

public class NeuronioKohonen extends Neuronio{

	private double[] pesos;
	private double sigmaZero;
	private double talVizinhaca;
	private double talAprendizagem;
	private double niZero;

	public NeuronioKohonen(int quantidadeDeAtributos, int posicaoX, int posicaoY,
			double sigmaZero, double talVizinhaca, double talAprendizagem,
			double niZero) {
		this(quantidadeDeAtributos, posicaoX, posicaoY, sigmaZero,
				talVizinhaca, talAprendizagem, niZero, null);
	}

	public NeuronioKohonen(int quantidadeDeAtributos, int posicaoX, int posicaoY,
			double sigmaZero, double talVizinhaca, double talAprendizagem,
			double niZero, DataSet dataSet) {
		super(posicaoX, posicaoY);
		this.sigmaZero = sigmaZero;
		this.talVizinhaca = talVizinhaca;
		this.talAprendizagem = talAprendizagem;
		this.niZero = niZero;
		this.pesos = new double[quantidadeDeAtributos];
		if (dataSet == null) {
			for (int i = 0; i < quantidadeDeAtributos; i++) {
				this.pesos[i] = Math.random();
			}
		} else {
			int index = (int) (Math.random() * dataSet.getRegistros().length);
			double[] registro = dataSet.getRegistros()[index];
			for (int i = 0; i < quantidadeDeAtributos; i++) {
				this.pesos[i] = registro[i];
			}
		}

	}
	
	public void setTalVizinhaca(double talVizinhaca) {
		this.talVizinhaca = talVizinhaca / Math.log10(sigmaZero);
	}

	public double[] getPesos() {
		return pesos;
	}

	public void setPesos(double[] pesos) {
		this.pesos = pesos;
	}

	public double atualizarPesos(double[] x, Coordenada vencedor, int tempo) {
		double retorno = 0;

		for (int i = 0; i < x.length; i++) {
			double atual = this.pesos[i];
			
			double sigmaVizinhaca = sigma(tempo);
			double h =  this.funcaoVizinhanca(vencedor, sigmaVizinhaca);
			double taxaAprendizagem = getTaxaAprendizagem(tempo);
			this.pesos[i] = this.pesos[i] + taxaAprendizagem
					* h * (x[i] - this.pesos[i]);
			retorno = retorno + Math.abs(atual - this.pesos[i]);
		}
		return retorno;
	}

	private double sigma(int tempo) {
		return this.sigmaZero * Math.exp(-tempo / this.talVizinhaca);
	}

	private double getTaxaAprendizagem(int tempo) {
		return this.niZero * Math.exp(-tempo / this.talAprendizagem);
	}
	

}
